import time
import hmac
import hashlib
import base64
import urllib.parse
import requests
import json
from datetime import datetime
from tenacity import retry, stop_after_attempt, wait_exponential
from aliyun_config import aliyun_config

class ImprovedAliyunIoTConnector:
    """改进的阿里云IoT设备连接器 - 使用配置管理"""
    
    def __init__(self, device_id):
        """初始化连接器
        
        Args:
            device_id: 设备ID (device1 或 device2)
        """
        self.device_id = device_id
        self.device_config = aliyun_config.get_device_config(device_id)
        
        if not self.device_config:
            raise Exception(f"找不到设备配置: {device_id}")
        
        self.product_key = self.device_config['ProductKey']
        self.device_name = self.device_config['DeviceName']
        self.device_secret = self.device_config['DeviceSecret']
        
        # 从全局配置获取账号信息
        self.access_key_id = aliyun_config.access_key_id
        self.access_key_secret = aliyun_config.access_key_secret
        self.region = aliyun_config.region
        self.endpoint = aliyun_config.endpoint
        self.instance_id = aliyun_config.instance_id
        
        self.last_data = {}
        self.last_fetch_time = 0
        
        print(f"✅ 初始化设备连接器: {self.device_name} (ProductKey: {self.product_key})")
    
    @property
    def name(self):
        """返回设备名称"""
        if self.device_config is None:
            return "未知设备"
        return self.device_config['name']
    
    def test_connection(self):
        """测试阿里云API端点可达性"""
        try:
            response = requests.get(self.endpoint, timeout=5)
            print(f"✅ 连接测试成功! 端点: {self.endpoint}, 状态码: {response.status_code}")
            return True
        except Exception as e:
            print(f"❌ 连接测试失败: {str(e)}")
            return False
    
    def _sign_request(self, params):
        """生成阿里云API签名"""
        # 1. 参数排序
        sorted_params = sorted(params.items())
        
        # 2. 构造规范化字符串（阿里云标准方法）
        canonicalized_query_string = urllib.parse.urlencode(sorted_params, quote_via=urllib.parse.quote)
        
        # 3. 构造签名字符串  
        string_to_sign = "POST&%2F&" + urllib.parse.quote(canonicalized_query_string, safe="")
        
        # 4. 计算签名
        key = self.access_key_secret + "&"
        signature = hmac.new(key.encode("utf-8"), string_to_sign.encode("utf-8"), hashlib.sha1).digest()
        return base64.b64encode(signature).decode("utf-8")
    
    @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
    def fetch_data(self):
        """获取设备最新数据"""
        try:
            print(f"📡 [fetch_data] 正在获取 {self.device_name} 数据...")
            
            # 构造请求参数
            params = {
                "Action": "QueryDevicePropertyStatus",
                "ProductKey": self.product_key,
                "DeviceName": self.device_name,
                "IotInstanceId": self.instance_id,
                "Format": "JSON",
                "Version": "2018-01-20",
                "AccessKeyId": self.access_key_id,
                "SignatureMethod": "HMAC-SHA1",
                "Timestamp": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
                "SignatureVersion": "1.0",
                "SignatureNonce": str(int(time.time() * 1000))
            }
            
            # 生成签名
            params["Signature"] = self._sign_request(params)
            
            # 发送请求
            response = requests.post(
                self.endpoint,
                params=params,
                timeout=10
            )
            
            print(f"📊 [fetch_data] 响应状态: {response.status_code}")
            
            if response.status_code == 200:
                data = response.json()
                print(f"📄 [fetch_data] 响应数据: {data}")
                
                if data.get("Success"):
                    self.last_data = data  # 保存完整的响应数据
                    self.last_fetch_time = time.time()
                    return self.last_data  # 返回完整的响应数据
                else:
                    print(f"❌ [fetch_data] API调用失败: {data.get('ErrorMessage', '未知错误')}")
                    return None
            else:
                print(f"❌ [fetch_data] HTTP请求失败: {response.status_code} - {response.text}")
                return None
                
        except Exception as e:
            print(f"❌ [fetch_data] {self.device_name} 数据获取错误: {str(e)}")
            return None
    
    def control_device(self, angle, speed_level=1, device_name=None):
        """控制设备 - 调整床板角度"""
        try:
            target_device = device_name or self.device_name
            print(f"🎮 [control_device] 控制设备 {target_device}: 角度={angle}°, 速度={speed_level}")
            
            # 构造控制参数 - 使用正确的阿里云IoT属性名称
            items_data = {
                "servoangle": angle,
                "servospeed": speed_level
            }
            
            params = {
                "Action": "SetDeviceProperty",
                "ProductKey": self.product_key,
                "DeviceName": target_device,
                "IotInstanceId": self.instance_id,
                "Items": json.dumps(items_data),
                "Format": "JSON",
                "Version": "2018-01-20",
                "AccessKeyId": self.access_key_id,
                "SignatureMethod": "HMAC-SHA1",
                "Timestamp": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
                "SignatureVersion": "1.0",
                "SignatureNonce": str(int(time.time() * 1000))
            }
            
            # 生成签名
            params["Signature"] = self._sign_request(params)
            
            print(f"📋 [control_device] 请求参数: {params}")
            
            # 发送控制指令
            response = requests.post(
                self.endpoint,
                params=params,
                timeout=10
            )
            
            print(f"📊 [control_device] 响应状态: {response.status_code}")
            
            if response.status_code == 200:
                data = response.json()
                print(f"📄 [control_device] 响应数据: {data}")
                
                if data.get("Success"):
                    print(f"✅ [control_device] 控制指令发送成功")
                    return {
                        "success": True,
                        "message": "指令下发成功",
                        "messageId": data.get("Data", {}).get("MessageId"),
                        "angle": angle,
                        "speed_level": speed_level
                    }
                else:
                    error_msg = data.get('ErrorMessage', '未知错误')
                    print(f"❌ [control_device] 控制失败: {error_msg}")
                    return {
                        "success": False,
                        "error": error_msg
                    }
            else:
                print(f"❌ [control_device] HTTP请求失败: {response.status_code} - {response.text}")
                return {
                    "success": False,
                    "error": f"HTTP请求失败: {response.status_code}"
                }
                
        except Exception as e:
            print(f"❌ [control_device] {target_device} 指令发送错误: {str(e)}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def send_command(self, command):
        """发送命令 - 为兼容性保留"""
        try:
            # 解析命令格式 SET_ANGLE:45
            if command.startswith("SET_ANGLE:"):
                angle = float(command.split(":")[1])
                return self.control_device(angle=angle, speed_level=1)
            else:
                print(f"❌ [send_command] 不支持的命令格式: {command}")
                return {"success": False, "error": "不支持的命令格式"}
        except Exception as e:
            print(f"❌ [send_command] 命令发送错误: {str(e)}")
            return {"success": False, "error": str(e)}
